package com.sprite.support.wechat.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.alibaba.fastjson.JSONObject;
import com.sprite.support.wechat.utils.model.Oauth2AccessToken;
import com.sprite.support.wechat.utils.model.WechatUserInfo;
import com.sprite.utils.UtilString;
import com.sprite.utils.cache.UtilCache;
import com.sprite.utils.http.UtilHttp;

public class Oauth2Utils {
	private static Logger logger = LoggerFactory.getLogger(Oauth2Utils.class);

	private static boolean enableCache = true;

	/**
	 * 是否开启缓存
	 * @param enableCache
	 */
	public static void setEnableCache(boolean enableCache) {
		Oauth2Utils.enableCache = enableCache;
	}

	/**
	 * key is AppId
	 */
	private final static UtilCache<Oauth2AccessToken> accessTokenCache = UtilCache.createUtilCache("_accessTokenCache_");


	private static boolean isSuccess(JSONObject response) {
		if(response == null) return false;

		Integer code = response.getInteger("errcode");
		if(code == null || Integer.valueOf(0).equals(code)) {
			return true;
		}

		return false;
	}

	/**
	 * code换取网页授权access_token
	 * <a href="https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842">详情</a>
	 * @param appId
	 * @param appSecret
	 * @param code
	 * @return
	 */
	public static Oauth2AccessToken getAccessToken(String appId, String appSecret, String code) {
		Oauth2AccessToken accessToken = null;
		if(enableCache){
			accessToken = accessTokenCache.get(appId);
		}

		String url = null;
		if(accessToken == null) {
			url = UtilString.place("https://api.weixin.qq.com/sns/oauth2/access_token?appid={}&secret={}&code={}&grant_type=authorization_code", appId, appSecret, code);
			accessToken = new Oauth2AccessToken(appId);
			if(enableCache){
				accessTokenCache.put(appId, accessToken);
			}
		}else if(accessToken.isExpired()){
			url = UtilString.place("https://api.weixin.qq.com/sns/oauth2/refresh_token?appid={}&grant_type=refresh_token&refresh_token={}", appId, accessToken.getRefreshToken());
		}

		if(!accessToken.isExpired()) {
			return accessToken;
		}

		try {
			String content = UtilHttp.getToText(url);

			logger.info("[getAccessToken] response content: {}", content);

			JSONObject jsonObject = JSONObject.parseObject(content);

			if(isSuccess(jsonObject)) {
				accessToken.setOpenId(jsonObject.getString("openid"));
				accessToken.setScope(jsonObject.getString("scope"));
				accessToken.refresh(jsonObject.getString("access_token"), jsonObject.getString("refresh_token"), jsonObject.getLongValue("expires_in") * 1000);
			}
		} catch (Exception e) {
			logger.error("[getAccessToken] error", e);
		}

		return accessToken;
	}

	/**
	 * 获取用户信息
	 * <a href="https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842">详情-第四步：拉取用户信息(需scope为 snsapi_userinfo)</a>
	 * @param accessToken
	 * @param openId
	 * @return
	 */
	public static WechatUserInfo getWechatUserInfo(String accessToken, String openId) {
		String url = UtilString.place(" https://api.weixin.qq.com/sns/userinfo?access_token={}&openid={}", accessToken, openId);
		try {
			String content = UtilHttp.getToText(url);

			logger.info("[getWechatUserInfo] response content: {}", content);

			JSONObject jsonObject = JSONObject.parseObject(content);

			if(!isSuccess(jsonObject)) {
				return null;
			}

			WechatUserInfo wechatUserInfo = new WechatUserInfo();
			wechatUserInfo.setCity(jsonObject.getString("city"));
			wechatUserInfo.setCountry(jsonObject.getString("country"));

			int sex = jsonObject.getIntValue("sex");
			if(sex != 0) {
				wechatUserInfo.setGender(sex == 1?"M":"F");
			}

			wechatUserInfo.setHeadimgurl(jsonObject.getString("headimgurl"));
			wechatUserInfo.setNickname(jsonObject.getString("nickname"));
			wechatUserInfo.setLanguage(jsonObject.getString("language"));
			wechatUserInfo.setOpenid(openId);
			wechatUserInfo.setProvince(jsonObject.getString("province"));
			wechatUserInfo.setRemark(jsonObject.getString("remark"));
			wechatUserInfo.setUnionid(jsonObject.getString("unionid"));
			return wechatUserInfo;
		} catch (Exception e) {
			logger.error("[getWechatUserInfo] error", e);
		}
		return null;
	}
	
}
